"""
商品素材相关数据模型

包括原始素材、处理后素材和素材分类等模型。
"""

from datetime import datetime
from typing import Dict, Any, Optional, List
import json
import enum

from sqlalchemy import Column, Integer, String, Float, Text, Boolean, ForeignKey, Index, DateTime, Enum
from sqlalchemy.orm import relationship, backref

from .base import BaseModel, JSONField


class MaterialStatus(enum.Enum):
    """素材状态枚举"""
    PENDING = "pending"          # 待处理
    PROCESSING = "processing"    # 处理中
    COMPLETED = "completed"      # 已完成
    FAILED = "failed"           # 处理失败
    ARCHIVED = "archived"       # 已归档


class MaterialType(enum.Enum):
    """素材类型枚举"""
    VIDEO = "video"             # 视频
    IMAGE = "image"             # 图片
    AUDIO = "audio"             # 音频
    DOCUMENT = "document"       # 文档
    OTHER = "other"             # 其他


class QualityLevel(enum.Enum):
    """质量等级枚举"""
    LOW = "low"                 # 低质量
    MEDIUM = "medium"           # 中等质量
    HIGH = "high"               # 高质量
    PREMIUM = "premium"         # 优质


class ProductRawMaterial(BaseModel):
    """
    商品原始素材表 - 待处理素材
    
    存储商品的原始素材文件，等待进一步处理。
    """
    
    __tablename__ = 'product_raw_materials'
    
    # 关联商品
    product_id = Column(Integer, ForeignKey('products.id'), nullable=False)
    product = relationship("Product", back_populates="raw_materials")
    
    # 文件信息
    file_name = Column(String(255), nullable=False)
    file_path = Column(String(500), nullable=False, index=True)
    file_size = Column(Integer, nullable=False)  # 字节
    file_hash = Column(String(64), nullable=True, index=True)  # SHA256哈希
    mime_type = Column(String(100), nullable=True)
    
    # 素材类型和状态
    material_type = Column(Enum(MaterialType), nullable=False, default=MaterialType.OTHER)
    status = Column(Enum(MaterialStatus), nullable=False, default=MaterialStatus.PENDING)
    
    # 处理信息
    upload_source = Column(String(100), nullable=True)  # 上传来源
    upload_batch = Column(String(100), nullable=True)   # 批次号
    processing_priority = Column(Integer, default=0)     # 处理优先级
    
    # 元数据信息 (JSON格式)
    material_metadata = Column(JSONField, nullable=True)
    
    # 处理记录
    processing_started_at = Column(DateTime, nullable=True)
    processing_completed_at = Column(DateTime, nullable=True)
    processing_error = Column(Text, nullable=True)
    
    # 备注信息
    notes = Column(Text, nullable=True)
    tags = Column(JSONField, nullable=True)  # 标签列表
    
    # 关联关系
    processed_materials = relationship("ProductMaterial", back_populates="raw_material", cascade="all, delete-orphan")
    
    # 索引
    __table_args__ = (
        Index('idx_raw_material_product_status', 'product_id', 'status'),
        Index('idx_raw_material_type_status', 'material_type', 'status'),
        Index('idx_raw_material_batch', 'upload_batch'),
    )
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        result = super().to_dict()
        result['material_type'] = self.material_type.value if self.material_type else None
        result['status'] = self.status.value if self.status else None
        result['metadata'] = self.get_metadata()
        result['tags'] = self.get_tags()
        return result
    
    def get_metadata(self) -> Dict[str, Any]:
        """获取元数据"""
        if self.material_metadata:
            return json.loads(self.material_metadata) if isinstance(self.material_metadata, str) else self.material_metadata
        return {}
    
    def get_tags(self) -> List[str]:
        """获取标签列表"""
        if self.tags:
            return json.loads(self.tags) if isinstance(self.tags, str) else self.tags
        return []
    
    def set_metadata(self, metadata: Dict[str, Any]):
        """设置元数据"""
        self.material_metadata = json.dumps(metadata, ensure_ascii=False)
    
    def add_tag(self, tag: str):
        """添加标签"""
        tags = self.get_tags()
        if tag not in tags:
            tags.append(tag)
            self.tags = json.dumps(tags, ensure_ascii=False)
    
    def start_processing(self):
        """开始处理"""
        self.status = MaterialStatus.PROCESSING
        self.processing_started_at = datetime.now()
        self.processing_error = None
    
    def complete_processing(self):
        """完成处理"""
        self.status = MaterialStatus.COMPLETED
        self.processing_completed_at = datetime.now()
        self.processing_error = None
    
    def fail_processing(self, error: str):
        """处理失败"""
        self.status = MaterialStatus.FAILED
        self.processing_completed_at = datetime.now()
        self.processing_error = error
    
    def get_processing_duration(self) -> Optional[float]:
        """获取处理时长(秒)"""
        if self.processing_started_at and self.processing_completed_at:
            delta = self.processing_completed_at - self.processing_started_at
            return delta.total_seconds()
        return None
    
    def __repr__(self):
        return f"<ProductRawMaterial(id={self.id}, product_id={self.product_id}, file_name='{self.file_name}', status='{self.status.value if self.status else None}')>"


class ProductMaterial(BaseModel):
    """
    商品素材表 - 已处理素材
    
    存储经过处理的商品素材，可用于制作成品。
    """
    
    __tablename__ = 'product_materials'
    
    # 关联商品和原始素材
    product_id = Column(Integer, ForeignKey('products.id'), nullable=False)
    product = relationship("Product", back_populates="materials")
    
    raw_material_id = Column(Integer, ForeignKey('product_raw_materials.id'), nullable=True)
    raw_material = relationship("ProductRawMaterial", back_populates="processed_materials")
    
    # 文件信息
    file_name = Column(String(255), nullable=False)
    file_path = Column(String(500), nullable=False, index=True)
    file_size = Column(Integer, nullable=False)
    file_hash = Column(String(64), nullable=True, index=True)
    mime_type = Column(String(100), nullable=True)
    
    # 素材属性
    material_type = Column(Enum(MaterialType), nullable=False, default=MaterialType.OTHER)
    quality_level = Column(Enum(QualityLevel), nullable=False, default=QualityLevel.MEDIUM)
    
    # 视频/图片特定属性
    duration = Column(Float, nullable=True)      # 时长(秒)
    width = Column(Integer, nullable=True)       # 宽度
    height = Column(Integer, nullable=True)      # 高度
    fps = Column(Float, nullable=True)           # 帧率
    bitrate = Column(Integer, nullable=True)     # 比特率
    
    # 处理信息
    processing_method = Column(String(100), nullable=True)  # 处理方法
    processing_params = Column(JSONField, nullable=True)    # 处理参数
    ai_analysis_result = Column(JSONField, nullable=True)   # AI分析结果
    
    # 分类信息
    ai_category = Column(String(100), nullable=True, index=True)  # AI分类结果
    ai_confidence = Column(Float, nullable=True)                  # AI置信度
    manual_category = Column(String(100), nullable=True)          # 人工分类
    
    # 质量评估
    quality_score = Column(Float, nullable=True)            # 质量评分 (0-1)
    technical_quality = Column(JSONField, nullable=True)    # 技术质量指标
    
    # 使用统计
    usage_count = Column(Integer, default=0)                # 使用次数
    last_used_at = Column(DateTime, nullable=True)          # 最后使用时间
    
    # 标签和描述
    tags = Column(JSONField, nullable=True)
    description = Column(Text, nullable=True)
    keywords = Column(Text, nullable=True)
    
    # 状态信息
    is_approved = Column(Boolean, default=False)            # 是否审核通过
    is_featured = Column(Boolean, default=False)            # 是否精选
    is_archived = Column(Boolean, default=False)            # 是否归档
    
    # 关联关系
    categories = relationship("ProductMaterialCategory", back_populates="material", cascade="all, delete-orphan")
    output_materials = relationship("ProductOutputMaterial", back_populates="material")
    
    # 索引
    __table_args__ = (
        Index('idx_material_product_type', 'product_id', 'material_type'),
        Index('idx_material_category_quality', 'ai_category', 'quality_level'),
        Index('idx_material_approved_featured', 'is_approved', 'is_featured'),
    )
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        result = super().to_dict()
        result['material_type'] = self.material_type.value if self.material_type else None
        result['quality_level'] = self.quality_level.value if self.quality_level else None
        result['processing_params'] = self.get_processing_params()
        result['ai_analysis_result'] = self.get_ai_analysis_result()
        result['technical_quality'] = self.get_technical_quality()
        result['tags'] = self.get_tags()
        return result
    
    def get_processing_params(self) -> Dict[str, Any]:
        """获取处理参数"""
        if self.processing_params:
            return json.loads(self.processing_params) if isinstance(self.processing_params, str) else self.processing_params
        return {}
    
    def get_ai_analysis_result(self) -> Dict[str, Any]:
        """获取AI分析结果"""
        if self.ai_analysis_result:
            return json.loads(self.ai_analysis_result) if isinstance(self.ai_analysis_result, str) else self.ai_analysis_result
        return {}
    
    def get_technical_quality(self) -> Dict[str, Any]:
        """获取技术质量指标"""
        if self.technical_quality:
            return json.loads(self.technical_quality) if isinstance(self.technical_quality, str) else self.technical_quality
        return {}
    
    def get_tags(self) -> List[str]:
        """获取标签列表"""
        if self.tags:
            return json.loads(self.tags) if isinstance(self.tags, str) else self.tags
        return []
    
    def increment_usage(self):
        """增加使用次数"""
        self.usage_count += 1
        self.last_used_at = datetime.now()
    
    def get_resolution_string(self) -> str:
        """获取分辨率字符串"""
        if self.width and self.height:
            return f"{self.width}x{self.height}"
        return "Unknown"
    
    def get_aspect_ratio(self) -> Optional[float]:
        """获取宽高比"""
        if self.width and self.height and self.height > 0:
            return self.width / self.height
        return None
    
    def is_high_quality(self) -> bool:
        """判断是否为高质量素材"""
        return (self.quality_level in [QualityLevel.HIGH, QualityLevel.PREMIUM] and
                self.is_approved and
                (self.quality_score is None or self.quality_score >= 0.7))
    
    def __repr__(self):
        return f"<ProductMaterial(id={self.id}, product_id={self.product_id}, file_name='{self.file_name}', category='{self.ai_category}')>"


class ProductMaterialCategory(BaseModel):
    """
    商品素材分类表

    存储素材的分类信息，支持多级分类和标签系统。
    """

    __tablename__ = 'product_material_categories'

    # 关联商品和素材
    product_id = Column(Integer, ForeignKey('products.id'), nullable=False)
    product = relationship("Product", back_populates="material_categories")

    material_id = Column(Integer, ForeignKey('product_materials.id'), nullable=False)
    material = relationship("ProductMaterial", back_populates="categories")

    # 分类信息
    category_name = Column(String(100), nullable=False, index=True)
    category_level = Column(Integer, default=1)  # 分类级别 (1=主分类, 2=子分类, etc.)
    parent_category = Column(String(100), nullable=True)  # 父分类

    # 分类来源
    classification_source = Column(String(50), nullable=False, default='manual')  # manual, ai, auto
    classifier_name = Column(String(100), nullable=True)  # 分类器名称
    confidence_score = Column(Float, nullable=True)       # 置信度

    # 分类详情
    classification_reason = Column(Text, nullable=True)   # 分类原因
    classification_metadata = Column(JSONField, nullable=True)  # 分类元数据

    # 验证信息
    is_verified = Column(Boolean, default=False)          # 是否已验证
    verified_by = Column(String(100), nullable=True)      # 验证人
    verified_at = Column(DateTime, nullable=True)         # 验证时间

    # 权重和优先级
    weight = Column(Float, default=1.0)                   # 分类权重
    priority = Column(Integer, default=0)                 # 优先级

    # 索引
    __table_args__ = (
        Index('idx_category_product_material', 'product_id', 'material_id'),
        Index('idx_category_name_level', 'category_name', 'category_level'),
        Index('idx_category_source_confidence', 'classification_source', 'confidence_score'),
    )

    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        result = super().to_dict()
        result['classification_metadata'] = self.get_classification_metadata()
        return result

    def get_classification_metadata(self) -> Dict[str, Any]:
        """获取分类元数据"""
        if self.classification_metadata:
            return json.loads(self.classification_metadata) if isinstance(self.classification_metadata, str) else self.classification_metadata
        return {}

    def set_classification_metadata(self, metadata: Dict[str, Any]):
        """设置分类元数据"""
        self.classification_metadata = json.dumps(metadata, ensure_ascii=False)

    def verify_classification(self, verified_by: str):
        """验证分类"""
        self.is_verified = True
        self.verified_by = verified_by
        self.verified_at = datetime.now()

    def get_full_category_path(self) -> str:
        """获取完整分类路径"""
        if self.parent_category:
            return f"{self.parent_category} > {self.category_name}"
        return self.category_name

    def is_ai_classified(self) -> bool:
        """判断是否为AI分类"""
        return self.classification_source == 'ai'

    def is_high_confidence(self, threshold: float = 0.8) -> bool:
        """判断是否为高置信度分类"""
        return self.confidence_score is not None and self.confidence_score >= threshold

    def __repr__(self):
        return f"<ProductMaterialCategory(id={self.id}, product_id={self.product_id}, material_id={self.material_id}, category='{self.category_name}')>"
